﻿using Model;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Timers;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;

namespace iCloudWatch
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        /// <summary>
        /// 文件监视器
        /// </summary>
        FileSystemWatcher watcher = new FileSystemWatcher();
        /// <summary>
        /// 定时器
        /// </summary>
        System.Timers.Timer timer;
        /// <summary>
        /// Model
        /// </summary>
        infoModel model = new infoModel();
        /// <summary>
        /// 倒计时
        /// </summary>
        int Second;
        /// <summary>
        /// 重启计数
        /// </summary>
        int ResetCount = 0;
        /// <summary>
        /// 配置文件路径
        /// </summary>
        string path = System.Windows.Forms.Application.StartupPath + "\\AppSettings.xml";

        /// <summary>
        /// 窗体启动
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                gpConfig.Enabled = false;
                //判断配置文件
                IsExistXML();
                //调用获取已下载总数方法
                WatchDownloadCount();
            }
            catch (Exception err)
            {
                MessageBox.Show(err.ToString());
            }
        }

        /// <summary>
        /// 判断配置文件是否存在
        /// </summary>
        private void IsExistXML()
        {
            if (!File.Exists(path))
            {
                //完全新建配置文件
                CreateXML(true) ;
                //读取配置文件
                ReadXML();
            }
            else
            {
                ReadXML();
            }
        }

       /// <summary>
       /// 读取配置文件
       /// </summary>
       /// <returns></returns>
        private infoModel ReadXML()
        {
            model.watchNames = new List<string>();
            XDocument doc = XDocument.Load(path);
            XElement root = doc.Root;
            XElement watchpath = root.Element("WatchPath");
            XElement watchtimes = root.Element("WatchTimes");
            XElement runpath = root.Element("RunPath");
            IEnumerable<XElement> enumerble = root.Elements("WatchNames");
            foreach (XElement item in enumerble)
            {
                foreach (XElement item1 in item.Elements())
                {
                    model.watchNames.Add(item1.Value.ToString());
                }
            }
            model.runPath = runpath.Value;
            model.watchPath = watchpath.Value;
            model.watchTimes = watchtimes.Value;
            txtRunPath.Text = model.runPath;
            txtWatchPath.Text = model.watchPath;
            txtWatchName.Lines = model.watchNames.ToArray();
            txtWatchTime.Text = (int.Parse(model.watchTimes) / 1000 / 60).ToString();
            return model;
        }

        /// <summary>
        /// 创建配置文件
        /// </summary>
        private void CreateXML(bool Create)
        {
            //  创建XML文档，存在就删除再生成
            XmlDocument doc = new XmlDocument();
            XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "GB2312", null);
            doc.AppendChild(dec);
            //  创建根结点
            XmlElement XMLroot = doc.CreateElement("root");
            doc.AppendChild(XMLroot);
            if (Create)
            {
                //创建监视路径节点
                XmlElement watchpath = doc.CreateElement("WatchPath");
                watchpath.InnerText = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures) + "\\iCloud Photos\\downloads";
                XMLroot.AppendChild(watchpath);
                //创建iCloud主程序运行目录
                XmlElement runpath = doc.CreateElement("RunPath");
                runpath.InnerText = @"C:\Program Files (x86)\Common Files\Apple\Internet Services\iCloud.exe";
                XMLroot.AppendChild(runpath);
                //创建监视时间
                XmlElement watchtimes = doc.CreateElement("WatchTimes");
                if (string.IsNullOrEmpty(txtWatchTime.Text))
                {
                    watchtimes.InnerText = (5 * 1000 * 60).ToString();
                }
                else
                {
                    watchtimes.InnerText = (int.Parse(txtWatchTime.Text.Trim()) * 1000 * 60).ToString();
                }
                XMLroot.AppendChild(watchtimes);
                //创建监视进程
                XmlElement watchnames = doc.CreateElement("WatchNames");
                List<string> list = GetWatchNames();
                for (int i = 0; i < list.Count; i++)
                {
                    if (!string.IsNullOrWhiteSpace(list[i]))
                    {
                        XmlElement names = doc.CreateElement("WatchNames");
                        names.SetAttribute("name", i.ToString());
                        names.InnerText = list[i].ToString().Trim();
                        watchnames.AppendChild(names);
                    }
                }
                XMLroot.AppendChild(watchnames);
            }
            else//修改配置文件
            {
                //创建监视路径节点
                XmlElement watchpath = doc.CreateElement("WatchPath");
                watchpath.InnerText = txtWatchPath.Text.Trim();
                XMLroot.AppendChild(watchpath);
                //创建iCloud主程序运行目录
                XmlElement runpath = doc.CreateElement("RunPath");
                runpath.InnerText = txtRunPath.Text.Trim();
                XMLroot.AppendChild(runpath);
                //创建监视时间
                XmlElement watchtimes = doc.CreateElement("WatchTimes");
                watchtimes.InnerText = (int.Parse(txtWatchTime.Text.Trim())*1000*60).ToString();
                XMLroot.AppendChild(watchtimes);
                //创建监视进程
                XmlElement watchnames = doc.CreateElement("WatchNames");
                List<string> list = GetWatchNames();
                for (int i = 0; i < list.Count; i++)
                {
                    if (!string.IsNullOrWhiteSpace(list[i]))
                    {
                        XmlElement names = doc.CreateElement("WatchNames");
                        names.SetAttribute("name", i.ToString());
                        names.InnerText = list[i].ToString().Trim();
                        watchnames.AppendChild(names);
                    }
                }
                XMLroot.AppendChild(watchnames);
            }
            string xmlFile = path;
            try
            {
                doc.Save(xmlFile);
            }
            catch (Exception err)
            {
                MessageBox.Show(err.ToString());
            }
        }

        /// <summary>
        /// 获取监视进程名
        /// </summary>
        /// <returns>进程名称集合</returns>
        private List<string> GetWatchNames()
        {
            List<string> list = new List<string>(txtWatchName.Lines);
            return list;
        }

        /// <summary>
        /// 启动新线程，查询已下载的照片总数
        /// </summary>
        private void WatchDownloadCount()
        {
            Thread th = new Thread(new ThreadStart(ThreadWatchDownloadCount));
            th.Start();
        }

        /// <summary>
        /// 查询照片线程内方法
        /// </summary>
        private void ThreadWatchDownloadCount()
        {
             List<string> list =  FindFile2(txtWatchPath.Text);
            if (lblDownloadCount.InvokeRequired)
            {
                while (lblDownloadCount.IsHandleCreated == false)
                {
                    if (lblDownloadCount.Disposing || lblDownloadCount.IsDisposed) return;
                }
                lblDownloadCount.Invoke(new Action<string>(s => { this.lblDownloadCount.Text = s; }), list.Count.ToString());
            }
            else
            {
                lblDownloadCount.Text = list.Count.ToString();
            }
            Thread.Sleep(1000);
        }

        /// <summary>
        /// 遍历监视文件夹内所有文件数量
        /// </summary>
        /// <param name="sSourcePath">被监视的文件路径</param>
        /// <returns></returns>
        public List<string> FindFile2(string sSourcePath)
        {
            List<String> list = new List<string>();
            try
            {
                //遍历文件夹
                DirectoryInfo theFolder = new DirectoryInfo(sSourcePath);
                FileInfo[] thefileInfo = theFolder.GetFiles("*.*", SearchOption.TopDirectoryOnly);
                foreach (FileInfo NextFile in thefileInfo)  //遍历文件
                {
                    list.Add(NextFile.FullName);
                }
                //遍历子文件夹
                DirectoryInfo[] dirInfo = theFolder.GetDirectories();
                foreach (DirectoryInfo NextFolder in dirInfo)
                {
                    FileInfo[] fileInfo = NextFolder.GetFiles("*.*", SearchOption.AllDirectories);
                    foreach (FileInfo NextFile in fileInfo)  //遍历文件
                    {
                        list.Add(NextFile.FullName);
                    }
                }
            }
            catch (Exception err)
            {
                MessageBox.Show(err.ToString());
            }
            return list;
        }

        /// <summary>
        /// 选择被监视的文件夹
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnWatchPath_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog fbd = new FolderBrowserDialog();
            if (fbd.ShowDialog() == DialogResult.OK)
            {
                txtWatchPath.Text = fbd.SelectedPath;
            }
        }

        /// <summary>
        /// 选择iCloud主程序
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnRunPath_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "iCloud主程序|*.exe";
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                txtRunPath.Text = ofd.FileName;
            }
        }

        /// <summary>
        /// 保存配置
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSave_Click(object sender, EventArgs e)
        {
            if (btnSave.Text == "配置")
            {
                btnSave.Text = "保存";
                btnStart.Enabled = false;
                gpConfig.Enabled = true;
            }
            else
            {
                btnSave.Text = "配置";
                btnStart.Enabled = true;
                gpConfig.Enabled = false;
                try
                {
                    CreateXML(false);
                    ReadXML();
                    MessageBox.Show("保存成功！");
                }
                catch (Exception err)
                {
                    MessageBox.Show("保存失败" + err);
                }
            }
        }

        /// <summary>
        /// 启动监视
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStart_Click(object sender, EventArgs e)
        {
            if (btnStart.Text == "开始监视")
            {
                btnStart.Text = "停止监视";
                btnSave.Enabled = false;
                StartReset();
                Second = int.Parse(model.watchTimes) / 1000;
                WatcherStrat(model.watchPath, "*.*");
            }
            else
            {
                btnStart.Text = "开始监视";
                btnSave.Enabled = true;
                timer.Stop();
            }
        }

        /// <summary>
        /// 目录动作监视
        /// </summary>
        /// <param name="path"></param>
        /// <param name="filter"></param>
        #region 目录动作监视
        private void WatcherStrat(string path, string filter)
        {
            watcher.Path = path;
            watcher.Filter = filter;
            watcher.Changed += new FileSystemEventHandler(OnProcess);
            watcher.Created += new FileSystemEventHandler(OnProcess);
            watcher.Deleted += new FileSystemEventHandler(OnProcess);
            watcher.Renamed += new RenamedEventHandler(OnRenamed);
            watcher.EnableRaisingEvents = true;
            watcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.CreationTime | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.LastAccess
                       | NotifyFilters.LastWrite | NotifyFilters.Security | NotifyFilters.Size;
            watcher.IncludeSubdirectories = true;
        }

        private void OnProcess(object source, FileSystemEventArgs e)
        {
            if (e.ChangeType == WatcherChangeTypes.Created)
            {
                OnCreated(source, e);
            }
            else if (e.ChangeType == WatcherChangeTypes.Changed)
            {
                OnChanged(source, e);
            }
            else if (e.ChangeType == WatcherChangeTypes.Deleted)
            {
                OnDeleted(source, e);
            }
        }
        private void OnCreated(object source, FileSystemEventArgs e)
        {
            ThreadWatchDownloadCount();
            timer.Stop();
            Second = int.Parse(model.watchTimes) / 1000;
            timer.Start();
        }
        private static void OnChanged(object source, FileSystemEventArgs e)
        {
        }

        private static void OnDeleted(object source, FileSystemEventArgs e)
        {
        }

        private static void OnRenamed(object source, RenamedEventArgs e)
        {
        }
        #endregion

        /// <summary>
        /// 重启进程
        /// </summary>
        private void StopAndStart()
        {
            KillProcess();
            Thread.Sleep(10000);
            StartProcess(txtRunPath.Text.Trim());
            Second = int.Parse(model.watchTimes) / 1000;
            StartReset();
        }

        /// <summary>
        /// 启动指定进程
        /// </summary>
        /// <param name="Path">进程路径</param>
        public static void StartProcess(string Path)
        {
            System.Diagnostics.Process.Start(Path);
        }

        /// <summary>
        /// 关闭进程
        /// </summary>
        public void KillProcess()
        {
            Process[] processes = Process.GetProcesses();
            foreach (Process p in processes)
            {
                foreach (string line in txtWatchName.Lines)
                {
                    if (p.ProcessName.ToUpper()==line.Replace(".exe", "").ToUpper())
                    {
                        try
                        {
                            //MessageBox.Show("发现进程：" + p.ProcessName + "，正在关闭。。。");
                            p.Kill();
                            p.WaitForExit(); 
                        }
                        catch (Win32Exception e)
                        {
                            MessageBox.Show(e.Message.ToString()); 
                        }
                        catch (InvalidOperationException e)
                        {
                            MessageBox.Show(e.Message.ToString()); 
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 开始倒计时
        /// </summary>
        private void StartReset()
        {
            timer = new System.Timers.Timer
            {
                Enabled = true,
                Interval = 1000
            };
            timer.Elapsed += new System.Timers.ElapsedEventHandler(ResetSecond);
        }

        /// <summary>
        /// 倒计时显示到窗体
        /// </summary>
        /// <param name="source"></param>
        /// <param name="e"></param>
        private void ResetSecond(object source, ElapsedEventArgs e)
        {
            if (Second > 0)
            {
                if (lblResetTime.InvokeRequired)
                {
                    while (lblResetTime.IsHandleCreated == false)
                    {
                        if (lblResetTime.Disposing || lblResetTime.IsDisposed) return;
                    }
                    lblResetTime.Invoke(new Action<string>(s => { this.lblResetTime.Text = s; }), Second.ToString());
                }
                else
                {
                    lblResetTime.Text = Second.ToString();
                }
                Second--;
            }
            else
            {
                timer.Stop();
                lblRestartCount.Invoke(new Action<string>(s => { lblRestartCount.Text = s; }), (ResetCount += 1).ToString());
                StopAndStart();
            }
        }
    }
}
